﻿#region using statements

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using XNAGameEngine.Utility;

#endregion

namespace XNAGameEngine.Input
{
    public sealed partial class ManagerInput
    {
        #region Nested type: ManagerGamePadInput

        private sealed class ManagerGamePadInput
        {
            #region local fields

            /// <summary>
            /// reference to the input manager
            /// </summary>
            private readonly ManagerInput _inputManager;

            private Vector2 _thumbstickValue;

            #endregion

            #region properties

            /// <summary>
            /// Get the current state of the gamepad
            /// </summary>
            private GamePadState _CurrentGamePadState { get; set; }

            /// <summary>
            /// Get the last state of the gamepad
            /// </summary>
            private GamePadState _LastGamePadState { get; set; }

            #endregion

            #region constructors

            /// <summary>
            /// Default constructor, saves a reference to the InputManager
            /// </summary>
            /// <param name="inputManager">the input manager that creates this object</param>
            public ManagerGamePadInput(ManagerInput inputManager)
            {
                _inputManager = inputManager;
            }

            #endregion

            #region local methods

            /// <summary>
            /// Update the input devices
            /// </summary>
            /// <param name="gameTime">the game time reference object</param>
            public void Update(GameTime gameTime)
            {
                _CurrentGamePadState = GamePad.GetState(PlayerIndex.One);

                // For every key on the keyboard
                foreach (Buttons button in EnumParse.GetEnumValues<Buttons>())
                {
                    // If it is a new key press throw the key pressed event
                    if (WasButtonPressed(button))
                    {
                        switch (button)
                        {
                            case Buttons.LeftThumbstickDown:
                            case Buttons.LeftThumbstickLeft:
                            case Buttons.LeftThumbstickRight:
                            case Buttons.LeftThumbstickUp:
                                _thumbstickValue.X =
                                    _CurrentGamePadState.ThumbSticks.Left.X;
                                _thumbstickValue.Y =
                                    _CurrentGamePadState.ThumbSticks.Left.Y;
                                _inputManager.InputPressed(
                                    null, button, null, null, _thumbstickValue);
                                break;
                            case Buttons.RightThumbstickDown:
                            case Buttons.RightThumbstickLeft:
                            case Buttons.RightThumbstickRight:
                            case Buttons.RightThumbstickUp:
                                _thumbstickValue.X =
                                    _CurrentGamePadState.ThumbSticks.Right.X;
                                _thumbstickValue.Y =
                                    _CurrentGamePadState.ThumbSticks.Right.Y;
                                _inputManager.InputPressed(
                                    null, button, null, null, _thumbstickValue);
                                break;
                            case Buttons.LeftTrigger:
                                _inputManager.InputPressed(
                                    null, button, null,
                                    _CurrentGamePadState.Triggers.Left, null);
                                break;
                            case Buttons.RightTrigger:
                                _inputManager.InputPressed(
                                    null, button, null,
                                    _CurrentGamePadState.Triggers.Right, null);
                                break;
                            default:
                                _inputManager.InputPressed(
                                    null, button, null, null, null);
                                break;
                        }
                        continue;
                    }

                    // If it is a key release throw the key released event
                    if (WasButtonReleased(button))
                    {
                        _inputManager.InputReleased(
                            null, button, null, null, null);
                        continue;
                    }

                    // If it is being held throw the key held event
                    if (WasButtonHeld(button))
                    {
                        switch (button)
                        {
                            case Buttons.LeftThumbstickDown:
                            case Buttons.LeftThumbstickLeft:
                            case Buttons.LeftThumbstickRight:
                            case Buttons.LeftThumbstickUp:
                                _thumbstickValue.X =
                                    _CurrentGamePadState.ThumbSticks.Left.X;
                                _thumbstickValue.Y =
                                    _CurrentGamePadState.ThumbSticks.Left.Y;
                                _inputManager.InputHeld(
                                    null, button, null, null, _thumbstickValue);
                                break;
                            case Buttons.RightThumbstickDown:
                            case Buttons.RightThumbstickLeft:
                            case Buttons.RightThumbstickRight:
                            case Buttons.RightThumbstickUp:
                                _thumbstickValue.X =
                                    _CurrentGamePadState.ThumbSticks.Right.X;
                                _thumbstickValue.Y =
                                    _CurrentGamePadState.ThumbSticks.Right.Y;
                                _inputManager.InputHeld(
                                    null, button, null, null, _thumbstickValue);
                                break;
                            case Buttons.LeftTrigger:
                                _inputManager.InputHeld(
                                    null, button, null,
                                    _CurrentGamePadState.Triggers.Left, null);
                                break;
                            case Buttons.RightTrigger:
                                _inputManager.InputHeld(
                                    null, button, null,
                                    _CurrentGamePadState.Triggers.Right, null);
                                break;
                            default:
                                _inputManager.InputHeld(
                                    null, button, null, null, null);
                                break;
                        }
                        continue;
                    }
                }
                _LastGamePadState = _CurrentGamePadState;
            }

            /// <summary>
            /// Whether the specified Button is down for the first time this frame
            /// </summary>
            /// <param name="button">the Button to test</param>
            /// <returns>true if the Button was pressed this frame, false otherwise</returns>
            public bool WasButtonPressed(Buttons button)
            {
                return (_LastGamePadState.IsButtonUp(button)
                        && _CurrentGamePadState.IsButtonDown(button));
            }

            /// <summary>
            /// Whether the specified Button is up for the first time this frame
            /// </summary>
            /// <param name="button">the Button to test</param>
            /// <returns>true if the key was released this frame, false otherwise</returns>
            public bool WasButtonReleased(Buttons button)
            {
                return (_LastGamePadState.IsButtonDown(button)
                        && _CurrentGamePadState.IsButtonUp(button));
            }

            /// <summary>
            /// Whether the specified Button has been down for more than one frame
            /// </summary>
            /// <param name="button">the Button to test</param>
            /// <returns>true if the Button was held since the last frame, false otherwise</returns>
            public bool WasButtonHeld(Buttons button)
            {
                return (_LastGamePadState.IsButtonDown(button)
                        && _CurrentGamePadState.IsButtonDown(button));
            }

            #endregion
        }

        #endregion
    }
}